/*
 * =====================================================================================
 *       Filename:  copy_cmd.c
 *    Description:  
 *        Version:  2.0
 *        Created:  2017.06.03 17:51
 *         Author:  fujiajun (fjj), fujiajun@renren1.com
 *        Company:  HOOLINKS
 * =====================================================================================
 */

#include "xshell.h"

void copy_cmd(char* param[PARAMNUM]){
    // 对参数进行分析
    if(param[0] == NULL) {
        printf("copy：缺少操作数\n");
    } else {
        if(param[1] == NULL) {
            printf("copy：缺少操作数\n");
        } else {
            // 执行操作
            if(!is_exist(param[0])){
                // 源文件、目录不存在
                printf("copy：%s 源文件不存在\n", param[0]);

            } else if(is_folder(param[0]) && !is_folder(param[1])){
                // 直接复制源目录，制作目录副本
                folder_copy(param[0], param[1]);

            } else if(is_folder(param[0]) && is_folder(param[1])){

                // 将源目录复制到目标目录下
                folder_copy_to_folder(param[0], param[1]);
            } else if(!is_folder(param[1])){
                // 直接复制源文件，制作文件副本
                file_copy(param[0], param[1]);

            } else if(is_folder(param[1])){
                // 将源文件复制到目标目录下
                file_copy_to_folder(param[0], param[1]);

            }
        }
    }
}

/**
 * 
 */
void file_copy(char* src, char* des){
    FILE *input, *output;
    char ch;

    if((input = fopen(src, "r")) == NULL) {
        printf("%s 源文件打开失败\n", src);
        return;
    }

    if((output = fopen(des, "w")) == NULL) {
        fclose(input);
        printf("%s 目标文件打开失败\n", des);
        return;
    }

    ch = fgetc(input);

    while(!feof(input)){
        fputc(ch, output);
        ch = fgetc(input);
    }

    fclose(input);
    fclose(output);
    return;
}


/**
 * 
 */
void file_copy_to_folder(char* file, char* folder){
	char fileName[500]; //文件名称
	char fileDest[500]; //目标文件路径
    int i;
    int Length = strlen(file); //获得源文件路径名的长度

    //从后往前循环遍历源文件路径名
    for(i = Length - 1; i >= 0; i--) {
        if(file[i] == '/') {
            //提取斜杠后的文件名
            strncpy(fileName, file + i + 1, Length - i);
            break;
        }
    }

	//没有斜杠，路径名就是文件名
    if(i <= -1) {
		strcpy(fileName, file);
	} 
    
	//构造目标文件路径名
    strcpy(fileDest, folder);
    strcat(fileDest, "/");
    strcat(fileDest, fileName);

	//调用文件复制函数
	file_copy(file, fileDest);

    return; 
}


/**
 * 
 */
void folder_copy(char* src, char* des){
	DIR *dp; //目录指针
    struct dirent *entry; //读取目录返回的结构体
    char srcInside[500]; //源目录、文件路径名
    char desInside[500]; //目标目录、文件路径名

    if((dp = opendir(src))  ==  NULL) {
        printf("%s 目标目录打开失败\n", src);
        return;
    }

    //目标目录创建失败，目标目录已存在
    if(create_folder(des) != 0) {
		return;
	}

    //循环读取目录下所有条目信息
    while((entry = readdir(dp)) != NULL) {
		
        //创建对应条目的源、目标路径名
        strcpy(srcInside, src);
        strcpy(desInside, des);
        strcat(srcInside, "/");
        strcat(desInside, "/");
        strcat(srcInside, entry->d_name);
        strcat(desInside, entry->d_name);

        //如果条目是目录
        if(is_folder(srcInside)) {
            //忽略.和..目录
            if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
            //递归调用直接复制目录函数
            folder_copy(srcInside, desInside);
        } else {
			//如果是文件，调用文件复制函数
            file_copy(srcInside, desInside);
        }
    }

    return;
}


/**
 * 
 */
void folder_copy_to_folder(char* src, char* des){
    char folderName[500]; //源目录名称
    char folderDesPath[500]; //目标目录路径名
    int i;
    int Length = strlen(src);

    //从后往前循环遍历源文件路径名，从倒数第二个字符开始遍历
    for(i = Length - 2; i >= 0; i--) {
		//如果遇到斜杠
        if(src[i] == '/') {
            //提取斜杠后的目录名
            strncpy(folderName, src + i + 1, Length - i);
            break;
        }
    }

	//如果没有斜杠，路径名就是目录名
    if(i <= -1) {
		strcpy(folderName, src);
	} 

    //复制目标目录路径名
    strcpy(folderDesPath, des);

    //确认目标目录路径名以斜杠结尾
    if(folderDesPath[strlen(folderDesPath) - 1] != '/') {
		strcat(folderDesPath, "/");
	}

    //创建新的目标目录路径名
    strcat(folderDesPath, folderName);

    //调用直接复制目录函数
	folder_copy(src, folderDesPath);

    return;
}


//-1=创建失败;-2=同名文件已存在;0=创建成功
int create_folder(char* folder){
    char folderPath[500]; //目录路径名
    int i;
    int len;
    strcpy(folderPath, folder); //拷贝目录路径名
    len = strlen(folderPath);

    //确保路径名最后字符为斜杠
    if(folderPath[len - 1] != '/') {
        strcat(folderPath, "/");
        len++;
    }

    //循环遍历路径名，逐层往下创建目录
    for(i = 1; i < len; i++) {
        if(folderPath[i] == '/') {
			//将斜杠替换为结束符
            folderPath[i] = '\0'; 
            
			//尝试创建目录
            if(access(folderPath, F_OK) < 0) {
				
				//创建失败
                if(mkdir(folderPath, 0755) < 0) {
                    printf("mkdir '%s' 失败!\n错误的文件夹名称或权限被拒绝!\n", folderPath);
                    return -1;
                }
            } else if(!is_folder(folderPath)) {
				//已存在同名文件
                printf("无法创建目录 ‘%s’，文件已存在!\n", folder);
                return -2;
            }

			//替换回斜杠
            folderPath[i] = '/';
        }
    }

    return 0;
}